<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="generator" content="Asciidoctor 1.5.3">
<title>Spring Cloud Contract Advanced 2.1.3.BUILD-SNAPSHOT</title>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700">
<style>
/* Asciidoctor default stylesheet | MIT License | http://asciidoctor.org */
/* Remove comment around @import statement below when using as a custom stylesheet */
/*@import "https://fonts.googleapis.com/css?family=Open+Sans:300,300italic,400,400italic,600,600italic%7CNoto+Serif:400,400italic,700,700italic%7CDroid+Sans+Mono:400,700";*/
article,aside,details,figcaption,figure,footer,header,hgroup,main,nav,section,summary{display:block}
audio,canvas,video{display:inline-block}
audio:not([controls]){display:none;height:0}
[hidden],template{display:none}
script{display:none!important}
html{font-family:sans-serif;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}
body{margin:0}
a{background:transparent}
a:focus{outline:thin dotted}
a:active,a:hover{outline:0}
h1{font-size:2em;margin:.67em 0}
abbr[title]{border-bottom:1px dotted}
b,strong{font-weight:bold}
dfn{font-style:italic}
hr{-moz-box-sizing:content-box;box-sizing:content-box;height:0}
mark{background:#ff0;color:#000}
code,kbd,pre,samp{font-family:monospace;font-size:1em}
pre{white-space:pre-wrap}
q{quotes:"\201C" "\201D" "\2018" "\2019"}
small{font-size:80%}
sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
sup{top:-.5em}
sub{bottom:-.25em}
img{border:0}
svg:not(:root){overflow:hidden}
figure{margin:0}
fieldset{border:1px solid silver;margin:0 2px;padding:.35em .625em .75em}
legend{border:0;padding:0}
button,input,select,textarea{font-family:inherit;font-size:100%;margin:0}
button,input{line-height:normal}
button,select{text-transform:none}
button,html input[type="button"],input[type="reset"],input[type="submit"]{-webkit-appearance:button;cursor:pointer}
button[disabled],html input[disabled]{cursor:default}
input[type="checkbox"],input[type="radio"]{box-sizing:border-box;padding:0}
input[type="search"]{-webkit-appearance:textfield;-moz-box-sizing:content-box;-webkit-box-sizing:content-box;box-sizing:content-box}
input[type="search"]::-webkit-search-cancel-button,input[type="search"]::-webkit-search-decoration{-webkit-appearance:none}
button::-moz-focus-inner,input::-moz-focus-inner{border:0;padding:0}
textarea{overflow:auto;vertical-align:top}
table{border-collapse:collapse;border-spacing:0}
*,*:before,*:after{-moz-box-sizing:border-box;-webkit-box-sizing:border-box;box-sizing:border-box}
html,body{font-size:100%}
body{background:#fff;color:rgba(0,0,0,.8);padding:0;margin:0;font-family:"Noto Serif","DejaVu Serif",serif;font-weight:400;font-style:normal;line-height:1;position:relative;cursor:auto}
a:hover{cursor:pointer}
img,object,embed{max-width:100%;height:auto}
object,embed{height:100%}
img{-ms-interpolation-mode:bicubic}
.left{float:left!important}
.right{float:right!important}
.text-left{text-align:left!important}
.text-right{text-align:right!important}
.text-center{text-align:center!important}
.text-justify{text-align:justify!important}
.hide{display:none}
body{-webkit-font-smoothing:antialiased}
img,object,svg{display:inline-block;vertical-align:middle}
textarea{height:auto;min-height:50px}
select{width:100%}
.center{margin-left:auto;margin-right:auto}
.spread{width:100%}
p.lead,.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{font-size:1.21875em;line-height:1.6}
.subheader,.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{line-height:1.45;color:#7a2518;font-weight:400;margin-top:0;margin-bottom:.25em}
div,dl,dt,dd,ul,ol,li,h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6,pre,form,p,blockquote,th,td{margin:0;padding:0;direction:ltr}
a{color:#2156a5;text-decoration:underline;line-height:inherit}
a:hover,a:focus{color:#1d4b8f}
a img{border:none}
p{font-family:inherit;font-weight:400;font-size:1em;line-height:1.6;margin-bottom:1.25em;text-rendering:optimizeLegibility}
p aside{font-size:.875em;line-height:1.35;font-style:italic}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{font-family:"Open Sans","DejaVu Sans",sans-serif;font-weight:300;font-style:normal;color:#ba3925;text-rendering:optimizeLegibility;margin-top:1em;margin-bottom:.5em;line-height:1.0125em}
h1 small,h2 small,h3 small,#toctitle small,.sidebarblock>.content>.title small,h4 small,h5 small,h6 small{font-size:60%;color:#e99b8f;line-height:0}
h1{font-size:2.125em}
h2{font-size:1.6875em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.375em}
h4,h5{font-size:1.125em}
h6{font-size:1em}
hr{border:solid #ddddd8;border-width:1px 0 0;clear:both;margin:1.25em 0 1.1875em;height:0}
em,i{font-style:italic;line-height:inherit}
strong,b{font-weight:bold;line-height:inherit}
small{font-size:60%;line-height:inherit}
code{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;color:rgba(0,0,0,.9)}
ul,ol,dl{font-size:1em;line-height:1.6;margin-bottom:1.25em;list-style-position:outside;font-family:inherit}
ul,ol,ul.no-bullet,ol.no-bullet{margin-left:1.5em}
ul li ul,ul li ol{margin-left:1.25em;margin-bottom:0;font-size:1em}
ul.square li ul,ul.circle li ul,ul.disc li ul{list-style:inherit}
ul.square{list-style-type:square}
ul.circle{list-style-type:circle}
ul.disc{list-style-type:disc}
ul.no-bullet{list-style:none}
ol li ul,ol li ol{margin-left:1.25em;margin-bottom:0}
dl dt{margin-bottom:.3125em;font-weight:bold}
dl dd{margin-bottom:1.25em}
abbr,acronym{text-transform:uppercase;font-size:90%;color:rgba(0,0,0,.8);border-bottom:1px dotted #ddd;cursor:help}
abbr{text-transform:none}
blockquote{margin:0 0 1.25em;padding:.5625em 1.25em 0 1.1875em;border-left:1px solid #ddd}
blockquote cite{display:block;font-size:.9375em;color:rgba(0,0,0,.6)}
blockquote cite:before{content:"\2014 \0020"}
blockquote cite a,blockquote cite a:visited{color:rgba(0,0,0,.6)}
blockquote,blockquote p{line-height:1.6;color:rgba(0,0,0,.85)}
@media only screen and (min-width:768px){h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2}
h1{font-size:2.75em}
h2{font-size:2.3125em}
h3,#toctitle,.sidebarblock>.content>.title{font-size:1.6875em}
h4{font-size:1.4375em}}
table{background:#fff;margin-bottom:1.25em;border:solid 1px #dedede}
table thead,table tfoot{background:#f7f8f7;font-weight:bold}
table thead tr th,table thead tr td,table tfoot tr th,table tfoot tr td{padding:.5em .625em .625em;font-size:inherit;color:rgba(0,0,0,.8);text-align:left}
table tr th,table tr td{padding:.5625em .625em;font-size:inherit;color:rgba(0,0,0,.8)}
table tr.even,table tr.alt,table tr:nth-of-type(even){background:#f8f8f7}
table thead tr th,table tfoot tr th,table tbody tr td,table tr td,table tfoot tr td{display:table-cell;line-height:1.6}
body{tab-size:4}
h1,h2,h3,#toctitle,.sidebarblock>.content>.title,h4,h5,h6{line-height:1.2;word-spacing:-.05em}
h1 strong,h2 strong,h3 strong,#toctitle strong,.sidebarblock>.content>.title strong,h4 strong,h5 strong,h6 strong{font-weight:400}
.clearfix:before,.clearfix:after,.float-group:before,.float-group:after{content:" ";display:table}
.clearfix:after,.float-group:after{clear:both}
*:not(pre)>code{font-size:.9375em;font-style:normal!important;letter-spacing:0;padding:.1em .5ex;word-spacing:-.15em;background-color:#f7f7f8;-webkit-border-radius:4px;border-radius:4px;line-height:1.45;text-rendering:optimizeSpeed}
pre,pre>code{line-height:1.45;color:rgba(0,0,0,.9);font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;font-weight:400;text-rendering:optimizeSpeed}
.keyseq{color:rgba(51,51,51,.8)}
kbd{font-family:"Droid Sans Mono","DejaVu Sans Mono",monospace;display:inline-block;color:rgba(0,0,0,.8);font-size:.65em;line-height:1.45;background-color:#f7f7f7;border:1px solid #ccc;-webkit-border-radius:3px;border-radius:3px;-webkit-box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em white inset;box-shadow:0 1px 0 rgba(0,0,0,.2),0 0 0 .1em #fff inset;margin:0 .15em;padding:.2em .5em;vertical-align:middle;position:relative;top:-.1em;white-space:nowrap}
.keyseq kbd:first-child{margin-left:0}
.keyseq kbd:last-child{margin-right:0}
.menuseq,.menu{color:rgba(0,0,0,.8)}
b.button:before,b.button:after{position:relative;top:-1px;font-weight:400}
b.button:before{content:"[";padding:0 3px 0 2px}
b.button:after{content:"]";padding:0 2px 0 3px}
p a>code:hover{color:rgba(0,0,0,.9)}
#header,#content,#footnotes,#footer{width:100%;margin-left:auto;margin-right:auto;margin-top:0;margin-bottom:0;max-width:62.5em;*zoom:1;position:relative;padding-left:.9375em;padding-right:.9375em}
#header:before,#header:after,#content:before,#content:after,#footnotes:before,#footnotes:after,#footer:before,#footer:after{content:" ";display:table}
#header:after,#content:after,#footnotes:after,#footer:after{clear:both}
#content{margin-top:1.25em}
#content:before{content:none}
#header>h1:first-child{color:rgba(0,0,0,.85);margin-top:2.25rem;margin-bottom:0}
#header>h1:first-child+#toc{margin-top:8px;border-top:1px solid #ddddd8}
#header>h1:only-child,body.toc2 #header>h1:nth-last-child(2){border-bottom:1px solid #ddddd8;padding-bottom:8px}
#header .details{border-bottom:1px solid #ddddd8;line-height:1.45;padding-top:.25em;padding-bottom:.25em;padding-left:.25em;color:rgba(0,0,0,.6);display:-ms-flexbox;display:-webkit-flex;display:flex;-ms-flex-flow:row wrap;-webkit-flex-flow:row wrap;flex-flow:row wrap}
#header .details span:first-child{margin-left:-.125em}
#header .details span.email a{color:rgba(0,0,0,.85)}
#header .details br{display:none}
#header .details br+span:before{content:"\00a0\2013\00a0"}
#header .details br+span.author:before{content:"\00a0\22c5\00a0";color:rgba(0,0,0,.85)}
#header .details br+span#revremark:before{content:"\00a0|\00a0"}
#header #revnumber{text-transform:capitalize}
#header #revnumber:after{content:"\00a0"}
#content>h1:first-child:not([class]){color:rgba(0,0,0,.85);border-bottom:1px solid #ddddd8;padding-bottom:8px;margin-top:0;padding-top:1rem;margin-bottom:1.25rem}
#toc{border-bottom:1px solid #efefed;padding-bottom:.5em}
#toc>ul{margin-left:.125em}
#toc ul.sectlevel0>li>a{font-style:italic}
#toc ul.sectlevel0 ul.sectlevel1{margin:.5em 0}
#toc ul{font-family:"Open Sans","DejaVu Sans",sans-serif;list-style-type:none}
#toc li{line-height:1.3334;margin-top:.3334em}
#toc a{text-decoration:none}
#toc a:active{text-decoration:underline}
#toctitle{color:#7a2518;font-size:1.2em}
@media only screen and (min-width:768px){#toctitle{font-size:1.375em}
body.toc2{padding-left:15em;padding-right:0}
#toc.toc2{margin-top:0!important;background-color:#f8f8f7;position:fixed;width:15em;left:0;top:0;border-right:1px solid #efefed;border-top-width:0!important;border-bottom-width:0!important;z-index:1000;padding:1.25em 1em;height:100%;overflow:auto}
#toc.toc2 #toctitle{margin-top:0;margin-bottom:.8rem;font-size:1.2em}
#toc.toc2>ul{font-size:.9em;margin-bottom:0}
#toc.toc2 ul ul{margin-left:0;padding-left:1em}
#toc.toc2 ul.sectlevel0 ul.sectlevel1{padding-left:0;margin-top:.5em;margin-bottom:.5em}
body.toc2.toc-right{padding-left:0;padding-right:15em}
body.toc2.toc-right #toc.toc2{border-right-width:0;border-left:1px solid #efefed;left:auto;right:0}}
@media only screen and (min-width:1280px){body.toc2{padding-left:20em;padding-right:0}
#toc.toc2{width:20em}
#toc.toc2 #toctitle{font-size:1.375em}
#toc.toc2>ul{font-size:.95em}
#toc.toc2 ul ul{padding-left:1.25em}
body.toc2.toc-right{padding-left:0;padding-right:20em}}
#content #toc{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
#content #toc>:first-child{margin-top:0}
#content #toc>:last-child{margin-bottom:0}
#footer{max-width:100%;background-color:rgba(0,0,0,.8);padding:1.25em}
#footer-text{color:rgba(255,255,255,.8);line-height:1.44}
.sect1{padding-bottom:.625em}
@media only screen and (min-width:768px){.sect1{padding-bottom:1.25em}}
.sect1+.sect1{border-top:1px solid #efefed}
#content h1>a.anchor,h2>a.anchor,h3>a.anchor,#toctitle>a.anchor,.sidebarblock>.content>.title>a.anchor,h4>a.anchor,h5>a.anchor,h6>a.anchor{position:absolute;z-index:1001;width:1.5ex;margin-left:-1.5ex;display:block;text-decoration:none!important;visibility:hidden;text-align:center;font-weight:400}
#content h1>a.anchor:before,h2>a.anchor:before,h3>a.anchor:before,#toctitle>a.anchor:before,.sidebarblock>.content>.title>a.anchor:before,h4>a.anchor:before,h5>a.anchor:before,h6>a.anchor:before{content:"\00A7";font-size:.85em;display:block;padding-top:.1em}
#content h1:hover>a.anchor,#content h1>a.anchor:hover,h2:hover>a.anchor,h2>a.anchor:hover,h3:hover>a.anchor,#toctitle:hover>a.anchor,.sidebarblock>.content>.title:hover>a.anchor,h3>a.anchor:hover,#toctitle>a.anchor:hover,.sidebarblock>.content>.title>a.anchor:hover,h4:hover>a.anchor,h4>a.anchor:hover,h5:hover>a.anchor,h5>a.anchor:hover,h6:hover>a.anchor,h6>a.anchor:hover{visibility:visible}
#content h1>a.link,h2>a.link,h3>a.link,#toctitle>a.link,.sidebarblock>.content>.title>a.link,h4>a.link,h5>a.link,h6>a.link{color:#ba3925;text-decoration:none}
#content h1>a.link:hover,h2>a.link:hover,h3>a.link:hover,#toctitle>a.link:hover,.sidebarblock>.content>.title>a.link:hover,h4>a.link:hover,h5>a.link:hover,h6>a.link:hover{color:#a53221}
.audioblock,.imageblock,.literalblock,.listingblock,.stemblock,.videoblock{margin-bottom:1.25em}
.admonitionblock td.content>.title,.audioblock>.title,.exampleblock>.title,.imageblock>.title,.listingblock>.title,.literalblock>.title,.stemblock>.title,.openblock>.title,.paragraph>.title,.quoteblock>.title,table.tableblock>.title,.verseblock>.title,.videoblock>.title,.dlist>.title,.olist>.title,.ulist>.title,.qlist>.title,.hdlist>.title{text-rendering:optimizeLegibility;text-align:left;font-family:"Noto Serif","DejaVu Serif",serif;font-size:1rem;font-style:italic}
table.tableblock>caption.title{white-space:nowrap;overflow:visible;max-width:0}
.paragraph.lead>p,#preamble>.sectionbody>.paragraph:first-of-type p{color:rgba(0,0,0,.85)}
table.tableblock #preamble>.sectionbody>.paragraph:first-of-type p{font-size:inherit}
.admonitionblock>table{border-collapse:separate;border:0;background:none;width:100%}
.admonitionblock>table td.icon{text-align:center;width:80px}
.admonitionblock>table td.icon img{max-width:none}
.admonitionblock>table td.icon .title{font-weight:bold;font-family:"Open Sans","DejaVu Sans",sans-serif;text-transform:uppercase}
.admonitionblock>table td.content{padding-left:1.125em;padding-right:1.25em;border-left:1px solid #ddddd8;color:rgba(0,0,0,.6)}
.admonitionblock>table td.content>:last-child>:last-child{margin-bottom:0}
.exampleblock>.content{border-style:solid;border-width:1px;border-color:#e6e6e6;margin-bottom:1.25em;padding:1.25em;background:#fff;-webkit-border-radius:4px;border-radius:4px}
.exampleblock>.content>:first-child{margin-top:0}
.exampleblock>.content>:last-child{margin-bottom:0}
.sidebarblock{border-style:solid;border-width:1px;border-color:#e0e0dc;margin-bottom:1.25em;padding:1.25em;background:#f8f8f7;-webkit-border-radius:4px;border-radius:4px}
.sidebarblock>:first-child{margin-top:0}
.sidebarblock>:last-child{margin-bottom:0}
.sidebarblock>.content>.title{color:#7a2518;margin-top:0;text-align:center}
.exampleblock>.content>:last-child>:last-child,.exampleblock>.content .olist>ol>li:last-child>:last-child,.exampleblock>.content .ulist>ul>li:last-child>:last-child,.exampleblock>.content .qlist>ol>li:last-child>:last-child,.sidebarblock>.content>:last-child>:last-child,.sidebarblock>.content .olist>ol>li:last-child>:last-child,.sidebarblock>.content .ulist>ul>li:last-child>:last-child,.sidebarblock>.content .qlist>ol>li:last-child>:last-child{margin-bottom:0}
.literalblock pre,.listingblock pre:not(.highlight),.listingblock pre[class="highlight"],.listingblock pre[class^="highlight "],.listingblock pre.CodeRay,.listingblock pre.prettyprint{background:#f7f7f8}
.sidebarblock .literalblock pre,.sidebarblock .listingblock pre:not(.highlight),.sidebarblock .listingblock pre[class="highlight"],.sidebarblock .listingblock pre[class^="highlight "],.sidebarblock .listingblock pre.CodeRay,.sidebarblock .listingblock pre.prettyprint{background:#f2f1f1}
.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{-webkit-border-radius:4px;border-radius:4px;word-wrap:break-word;padding:1em;font-size:.8125em}
.literalblock pre.nowrap,.literalblock pre[class].nowrap,.listingblock pre.nowrap,.listingblock pre[class].nowrap{overflow-x:auto;white-space:pre;word-wrap:normal}
@media only screen and (min-width:768px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:.90625em}}
@media only screen and (min-width:1280px){.literalblock pre,.literalblock pre[class],.listingblock pre,.listingblock pre[class]{font-size:1em}}
.literalblock.output pre{color:#f7f7f8;background-color:rgba(0,0,0,.9)}
.listingblock pre.highlightjs{padding:0}
.listingblock pre.highlightjs>code{padding:1em;-webkit-border-radius:4px;border-radius:4px}
.listingblock pre.prettyprint{border-width:0}
.listingblock>.content{position:relative}
.listingblock code[data-lang]:before{display:none;content:attr(data-lang);position:absolute;font-size:.75em;top:.425rem;right:.5rem;line-height:1;text-transform:uppercase;color:#999}
.listingblock:hover code[data-lang]:before{display:block}
.listingblock.terminal pre .command:before{content:attr(data-prompt);padding-right:.5em;color:#999}
.listingblock.terminal pre .command:not([data-prompt]):before{content:"$"}
table.pyhltable{border-collapse:separate;border:0;margin-bottom:0;background:none}
table.pyhltable td{vertical-align:top;padding-top:0;padding-bottom:0;line-height:1.45}
table.pyhltable td.code{padding-left:.75em;padding-right:0}
pre.pygments .lineno,table.pyhltable td:not(.code){color:#999;padding-left:0;padding-right:.5em;border-right:1px solid #ddddd8}
pre.pygments .lineno{display:inline-block;margin-right:.25em}
table.pyhltable .linenodiv{background:none!important;padding-right:0!important}
.quoteblock{margin:0 1em 1.25em 1.5em;display:table}
.quoteblock>.title{margin-left:-1.5em;margin-bottom:.75em}
.quoteblock blockquote,.quoteblock blockquote p{color:rgba(0,0,0,.85);font-size:1.15rem;line-height:1.75;word-spacing:.1em;letter-spacing:0;font-style:italic;text-align:justify}
.quoteblock blockquote{margin:0;padding:0;border:0}
.quoteblock blockquote:before{content:"\201c";float:left;font-size:2.75em;font-weight:bold;line-height:.6em;margin-left:-.6em;color:#7a2518;text-shadow:0 1px 2px rgba(0,0,0,.1)}
.quoteblock blockquote>.paragraph:last-child p{margin-bottom:0}
.quoteblock .attribution{margin-top:.5em;margin-right:.5ex;text-align:right}
.quoteblock .quoteblock{margin-left:0;margin-right:0;padding:.5em 0;border-left:3px solid rgba(0,0,0,.6)}
.quoteblock .quoteblock blockquote{padding:0 0 0 .75em}
.quoteblock .quoteblock blockquote:before{display:none}
.verseblock{margin:0 1em 1.25em 1em}
.verseblock pre{font-family:"Open Sans","DejaVu Sans",sans;font-size:1.15rem;color:rgba(0,0,0,.85);font-weight:300;text-rendering:optimizeLegibility}
.verseblock pre strong{font-weight:400}
.verseblock .attribution{margin-top:1.25rem;margin-left:.5ex}
.quoteblock .attribution,.verseblock .attribution{font-size:.9375em;line-height:1.45;font-style:italic}
.quoteblock .attribution br,.verseblock .attribution br{display:none}
.quoteblock .attribution cite,.verseblock .attribution cite{display:block;letter-spacing:-.025em;color:rgba(0,0,0,.6)}
.quoteblock.abstract{margin:0 0 1.25em 0;display:block}
.quoteblock.abstract blockquote,.quoteblock.abstract blockquote p{text-align:left;word-spacing:0}
.quoteblock.abstract blockquote:before,.quoteblock.abstract blockquote p:first-of-type:before{display:none}
table.tableblock{max-width:100%;border-collapse:separate}
table.tableblock td>.paragraph:last-child p>p:last-child,table.tableblock th>p:last-child,table.tableblock td>p:last-child{margin-bottom:0}
table.tableblock,th.tableblock,td.tableblock{border:0 solid #dedede}
table.grid-all th.tableblock,table.grid-all td.tableblock{border-width:0 1px 1px 0}
table.grid-all tfoot>tr>th.tableblock,table.grid-all tfoot>tr>td.tableblock{border-width:1px 1px 0 0}
table.grid-cols th.tableblock,table.grid-cols td.tableblock{border-width:0 1px 0 0}
table.grid-all *>tr>.tableblock:last-child,table.grid-cols *>tr>.tableblock:last-child{border-right-width:0}
table.grid-rows th.tableblock,table.grid-rows td.tableblock{border-width:0 0 1px 0}
table.grid-all tbody>tr:last-child>th.tableblock,table.grid-all tbody>tr:last-child>td.tableblock,table.grid-all thead:last-child>tr>th.tableblock,table.grid-rows tbody>tr:last-child>th.tableblock,table.grid-rows tbody>tr:last-child>td.tableblock,table.grid-rows thead:last-child>tr>th.tableblock{border-bottom-width:0}
table.grid-rows tfoot>tr>th.tableblock,table.grid-rows tfoot>tr>td.tableblock{border-width:1px 0 0 0}
table.frame-all{border-width:1px}
table.frame-sides{border-width:0 1px}
table.frame-topbot{border-width:1px 0}
th.halign-left,td.halign-left{text-align:left}
th.halign-right,td.halign-right{text-align:right}
th.halign-center,td.halign-center{text-align:center}
th.valign-top,td.valign-top{vertical-align:top}
th.valign-bottom,td.valign-bottom{vertical-align:bottom}
th.valign-middle,td.valign-middle{vertical-align:middle}
table thead th,table tfoot th{font-weight:bold}
tbody tr th{display:table-cell;line-height:1.6;background:#f7f8f7}
tbody tr th,tbody tr th p,tfoot tr th,tfoot tr th p{color:rgba(0,0,0,.8);font-weight:bold}
p.tableblock>code:only-child{background:none;padding:0}
p.tableblock{font-size:1em}
td>div.verse{white-space:pre}
ol{margin-left:1.75em}
ul li ol{margin-left:1.5em}
dl dd{margin-left:1.125em}
dl dd:last-child,dl dd:last-child>:last-child{margin-bottom:0}
ol>li p,ul>li p,ul dd,ol dd,.olist .olist,.ulist .ulist,.ulist .olist,.olist .ulist{margin-bottom:.625em}
ul.unstyled,ol.unnumbered,ul.checklist,ul.none{list-style-type:none}
ul.unstyled,ol.unnumbered,ul.checklist{margin-left:.625em}
ul.checklist li>p:first-child>.fa-square-o:first-child,ul.checklist li>p:first-child>.fa-check-square-o:first-child{width:1em;font-size:.85em}
ul.checklist li>p:first-child>input[type="checkbox"]:first-child{width:1em;position:relative;top:1px}
ul.inline{margin:0 auto .625em auto;margin-left:-1.375em;margin-right:0;padding:0;list-style:none;overflow:hidden}
ul.inline>li{list-style:none;float:left;margin-left:1.375em;display:block}
ul.inline>li>*{display:block}
.unstyled dl dt{font-weight:400;font-style:normal}
ol.arabic{list-style-type:decimal}
ol.decimal{list-style-type:decimal-leading-zero}
ol.loweralpha{list-style-type:lower-alpha}
ol.upperalpha{list-style-type:upper-alpha}
ol.lowerroman{list-style-type:lower-roman}
ol.upperroman{list-style-type:upper-roman}
ol.lowergreek{list-style-type:lower-greek}
.hdlist>table,.colist>table{border:0;background:none}
.hdlist>table>tbody>tr,.colist>table>tbody>tr{background:none}
td.hdlist1,td.hdlist2{vertical-align:top;padding:0 .625em}
td.hdlist1{font-weight:bold;padding-bottom:1.25em}
.literalblock+.colist,.listingblock+.colist{margin-top:-.5em}
.colist>table tr>td:first-of-type{padding:0 .75em;line-height:1}
.colist>table tr>td:last-of-type{padding:.25em 0}
.thumb,.th{line-height:0;display:inline-block;border:solid 4px #fff;-webkit-box-shadow:0 0 0 1px #ddd;box-shadow:0 0 0 1px #ddd}
.imageblock.left,.imageblock[style*="float: left"]{margin:.25em .625em 1.25em 0}
.imageblock.right,.imageblock[style*="float: right"]{margin:.25em 0 1.25em .625em}
.imageblock>.title{margin-bottom:0}
.imageblock.thumb,.imageblock.th{border-width:6px}
.imageblock.thumb>.title,.imageblock.th>.title{padding:0 .125em}
.image.left,.image.right{margin-top:.25em;margin-bottom:.25em;display:inline-block;line-height:0}
.image.left{margin-right:.625em}
.image.right{margin-left:.625em}
a.image{text-decoration:none;display:inline-block}
a.image object{pointer-events:none}
sup.footnote,sup.footnoteref{font-size:.875em;position:static;vertical-align:super}
sup.footnote a,sup.footnoteref a{text-decoration:none}
sup.footnote a:active,sup.footnoteref a:active{text-decoration:underline}
#footnotes{padding-top:.75em;padding-bottom:.75em;margin-bottom:.625em}
#footnotes hr{width:20%;min-width:6.25em;margin:-.25em 0 .75em 0;border-width:1px 0 0 0}
#footnotes .footnote{padding:0 .375em 0 .225em;line-height:1.3334;font-size:.875em;margin-left:1.2em;text-indent:-1.05em;margin-bottom:.2em}
#footnotes .footnote a:first-of-type{font-weight:bold;text-decoration:none}
#footnotes .footnote:last-of-type{margin-bottom:0}
#content #footnotes{margin-top:-.625em;margin-bottom:0;padding:.75em 0}
.gist .file-data>table{border:0;background:#fff;width:100%;margin-bottom:0}
.gist .file-data>table td.line-data{width:99%}
div.unbreakable{page-break-inside:avoid}
.big{font-size:larger}
.small{font-size:smaller}
.underline{text-decoration:underline}
.overline{text-decoration:overline}
.line-through{text-decoration:line-through}
.aqua{color:#00bfbf}
.aqua-background{background-color:#00fafa}
.black{color:#000}
.black-background{background-color:#000}
.blue{color:#0000bf}
.blue-background{background-color:#0000fa}
.fuchsia{color:#bf00bf}
.fuchsia-background{background-color:#fa00fa}
.gray{color:#606060}
.gray-background{background-color:#7d7d7d}
.green{color:#006000}
.green-background{background-color:#007d00}
.lime{color:#00bf00}
.lime-background{background-color:#00fa00}
.maroon{color:#600000}
.maroon-background{background-color:#7d0000}
.navy{color:#000060}
.navy-background{background-color:#00007d}
.olive{color:#606000}
.olive-background{background-color:#7d7d00}
.purple{color:#600060}
.purple-background{background-color:#7d007d}
.red{color:#bf0000}
.red-background{background-color:#fa0000}
.silver{color:#909090}
.silver-background{background-color:#bcbcbc}
.teal{color:#006060}
.teal-background{background-color:#007d7d}
.white{color:#bfbfbf}
.white-background{background-color:#fafafa}
.yellow{color:#bfbf00}
.yellow-background{background-color:#fafa00}
span.icon>.fa{cursor:default}
.admonitionblock td.icon [class^="fa icon-"]{font-size:2.5em;text-shadow:1px 1px 2px rgba(0,0,0,.5);cursor:default}
.admonitionblock td.icon .icon-note:before{content:"\f05a";color:#19407c}
.admonitionblock td.icon .icon-tip:before{content:"\f0eb";text-shadow:1px 1px 2px rgba(155,155,0,.8);color:#111}
.admonitionblock td.icon .icon-warning:before{content:"\f071";color:#bf6900}
.admonitionblock td.icon .icon-caution:before{content:"\f06d";color:#bf3400}
.admonitionblock td.icon .icon-important:before{content:"\f06a";color:#bf0000}
.conum[data-value]{display:inline-block;color:#fff!important;background-color:rgba(0,0,0,.8);-webkit-border-radius:100px;border-radius:100px;text-align:center;font-size:.75em;width:1.67em;height:1.67em;line-height:1.67em;font-family:"Open Sans","DejaVu Sans",sans-serif;font-style:normal;font-weight:bold}
.conum[data-value] *{color:#fff!important}
.conum[data-value]+b{display:none}
.conum[data-value]:after{content:attr(data-value)}
pre .conum[data-value]{position:relative;top:-.125em}
b.conum *{color:inherit!important}
.conum:not([data-value]):empty{display:none}
dt,th.tableblock,td.content,div.footnote{text-rendering:optimizeLegibility}
h1,h2,p,td.content,span.alt{letter-spacing:-.01em}
p strong,td.content strong,div.footnote strong{letter-spacing:-.005em}
p,blockquote,dt,td.content,span.alt{font-size:1.0625rem}
p{margin-bottom:1.25rem}
.sidebarblock p,.sidebarblock dt,.sidebarblock td.content,p.tableblock{font-size:1em}
.exampleblock>.content{background-color:#fffef7;border-color:#e0e0dc;-webkit-box-shadow:0 1px 4px #e0e0dc;box-shadow:0 1px 4px #e0e0dc}
.print-only{display:none!important}
@media print{@page{margin:1.25cm .75cm}
*{-webkit-box-shadow:none!important;box-shadow:none!important;text-shadow:none!important}
a{color:inherit!important;text-decoration:underline!important}
a.bare,a[href^="#"],a[href^="mailto:"]{text-decoration:none!important}
a[href^="http:"]:not(.bare):after,a[href^="https:"]:not(.bare):after{content:"(" attr(href) ")";display:inline-block;font-size:.875em;padding-left:.25em}
abbr[title]:after{content:" (" attr(title) ")"}
pre,blockquote,tr,img,object,svg{page-break-inside:avoid}
thead{display:table-header-group}
svg{max-width:100%}
p,blockquote,dt,td.content{font-size:1em;orphans:3;widows:3}
h2,h3,#toctitle,.sidebarblock>.content>.title{page-break-after:avoid}
#toc,.sidebarblock,.exampleblock>.content{background:none!important}
#toc{border-bottom:1px solid #ddddd8!important;padding-bottom:0!important}
.sect1{padding-bottom:0!important}
.sect1+.sect1{border:0!important}
#header>h1:first-child{margin-top:1.25rem}
body.book #header{text-align:center}
body.book #header>h1:first-child{border:0!important;margin:2.5em 0 1em 0}
body.book #header .details{border:0!important;display:block;padding:0!important}
body.book #header .details span:first-child{margin-left:0!important}
body.book #header .details br{display:block}
body.book #header .details br+span:before{content:none!important}
body.book #toc{border:0!important;text-align:left!important;padding:0!important;margin:0!important}
body.book #toc,body.book #preamble,body.book h1.sect0,body.book .sect1>h2{page-break-before:always}
.listingblock code[data-lang]:before{display:block}
#footer{background:none!important;padding:0 .9375em}
#footer-text{color:rgba(0,0,0,.6)!important;font-size:.9em}
.hide-on-print{display:none!important}
.print-only{display:block!important}
.hide-for-print{display:none!important}
.show-for-print{display:inherit!important}}
</style>
<style>
.hidden {
	display: none;
}

.switch {
	border-width: 1px 1px 0 1px;
	border-style: solid;
	border-color: #7a2518;
	display: inline-block;
}

.switch--item {
	padding: 10px;
	background-color: #ffffff;
	color: #7a2518;
	display: inline-block;
	cursor: pointer;
}

.switch--item.selected {
	background-color: #7a2519;
	color: #ffffff;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/zepto/1.2.0/zepto.min.js"></script>
<script type="text/javascript">
function addBlockSwitches() {
	$('.primary').each(function() {
		primary = $(this);
		createSwitchItem(primary, createBlockSwitch(primary)).item.addClass("selected");
		primary.children('.title').remove();
	});
	$('.secondary').each(function(idx, node) {
		secondary = $(node);
		primary = findPrimary(secondary);
		switchItem = createSwitchItem(secondary, primary.children('.switch'));
		switchItem.content.addClass('hidden');
		findPrimary(secondary).append(switchItem.content);
		secondary.remove();
	});
}

function createBlockSwitch(primary) {
	blockSwitch = $('<div class="switch"></div>');
	primary.prepend(blockSwitch);
	return blockSwitch;
}

function findPrimary(secondary) {
	candidate = secondary.prev();
	while (!candidate.is('.primary')) {
		candidate = candidate.prev();
	}
	return candidate;
}

function createSwitchItem(block, blockSwitch) {
	blockName = block.children('.title').text();
	content = block.children('.content').first().append(block.next('.colist'));
	item = $('<div class="switch--item">' + blockName + '</div>');
	item.on('click', '', content, function(e) {
		$(this).addClass('selected');
		$(this).siblings().removeClass('selected');
		e.data.siblings('.content').addClass('hidden');
		e.data.removeClass('hidden');
	});
	blockSwitch.append(item);
	return {'item': item, 'content': content};
}

$(addBlockSwitches);
</script>
</head>

<body class="article toc2 toc-left">
<div id="header">
<h1>Spring Cloud Contract Advanced 2.1.3.BUILD-SNAPSHOT</h1>
<div id="toc" class="toc2">
<div id="toctitle">Table of Contents</div>
<ul class="sectlevel1">
<li><a href="#_scenarios">Scenarios</a></li>
<li><a href="#_flow">Flow</a></li>
<li><a href="#_tutorial">Tutorial</a>
<ul class="sectlevel2">
<li><a href="#_consumer_flow_1">Consumer Flow 1</a>
<ul class="sectlevel3">
<li><a href="#_cloned_producer">Cloned Producer</a></li>
</ul>
</li>
<li><a href="#_producer_flow_1">Producer Flow 1</a>
<ul class="sectlevel3">
<li><a href="#_ide_setup">IDE setup</a></li>
<li><a href="#_setting_up_the_spring_cloud_contract_plugin">Setting up the Spring Cloud Contract plugin</a></li>
<li><a href="#_generating_tests_from_contracts">Generating tests from contracts</a></li>
<li><a href="#_fixing_broken_http_tests">Fixing broken HTTP tests</a></li>
</ul>
</li>
</ul>
</li>
<li><a href="#_solutions">Solutions</a>
<ul class="sectlevel2">
<li><a href="#_written_consumer_tests">Written consumer tests</a></li>
<li><a href="#_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</a></li>
<li><a href="#_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</a></li>
<li><a href="#_missing_consumer_controller_code">Missing consumer controller code</a></li>
<li><a href="#_stub_logs">Stub Logs</a></li>
<li><a href="#_beer_request">Beer Request</a></li>
<li><a href="#_missing_listener_code">Missing listener code</a></li>
<li><a href="#_missing_triggers">Missing triggers</a></li>
<li><a href="#_messaging_dsls">Messaging DSLs</a></li>
<li><a href="#_producercontroller_implementation">ProducerController implementation</a></li>
<li><a href="#_beerrestbase">BeerRestBase</a></li>
<li><a href="#_beermessagingbase">BeerMessagingBase</a></li>
<li><a href="#_messaging_implementation">Messaging implementation</a></li>
<li><a href="#_buycontroller">BuyController</a></li>
<li><a href="#_missing_assert_methods">Missing assert methods</a></li>
<li><a href="#_grumpy_contracts">Grumpy contracts</a></li>
</ul>
</li>
<li><a href="#_back_to_the_main_page">Back to the Main Page</a></li>
</ul>
</div>
</div>
<div id="content">
<div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>In this tutorial, we keep the contracts together with the producer code, and we check
out the more advanced concepts behind Spring Cloud Contract.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_scenarios">Scenarios</h2>
<div class="sectionbody">
<div class="paragraph">
<p>We&#8217;ll try to code the following scenario:</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/grumpy_1.png" alt="grumpy 1">
</div>
<div class="title">Figure 1. Grumpy bartender that doesn&#8217;t want to sell any alcohol</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
<div class="imageblock">
<div class="content">
<img src="../images/grumpy_2.png" alt="grumpy 2">
</div>
<div class="title">Figure 2. But the beer will always be sold to Josh Long</div>
</div>
<div class="paragraph">
<p>&#160;
&#160;</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_flow">Flow</h2>
<div class="sectionbody">
<div class="imageblock">
<div class="content">
<img src="../images/flow.png" alt="flow">
</div>
<div class="title">Figure 3. Consumer Driven Contract flow</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_tutorial">Tutorial</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Using Consumer Driven Contracts is like using TDD at the architecture level. We start by
writing a test on the consumer side.</p>
</div>
<div class="sect2">
<h3 id="_consumer_flow_1">Consumer Flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/consumer_flow_1.png" alt="consumer flow 1">
</div>
<div class="title">Figure 4. Interact with cloned producer code</div>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
This tutorial assumes that you completed the previous tutorials and that the
consumer code has already been set up with appropriate dependencies.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Let&#8217;s open the <code>GrumpyBartenderControllerTest</code>. The first step is to write the missing
implementation of the tests. Basing on the previously shown requirements, the controller
should resemble the following:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_fail_to_sell_beer() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/grumpy")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(jsonPath("$.whatTheBartenderSaid").value("You're drunk [marcin]. Go home!"))
				.andExpect(jsonPath("$.whatDoWeDo").value("Go to another bar"));
		//remove::end[]
	}

	@Test public void should_sell_beer_to_Josh() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/grumpy")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("starbuxman", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(jsonPath("$.whatTheBartenderSaid").value("There you go Josh!"))
				.andExpect(jsonPath("$.whatDoWeDo").value("Enjoy!"));
		//remove::end[]
	}</code></pre>
</div>
</div>
<div class="paragraph">
<p>If we run the tests now, they fail. Let&#8217;s now check out the producer&#8217;s code
to define the missing contract. Open the <code>producer_advanced</code> project.</p>
</div>
<div class="sect3">
<h4 id="_cloned_producer">Cloned Producer</h4>
<div class="paragraph">
<p>As usual in these tutorials, we do not clone the producer&#8217;s code, even though we would do
so in a real life scenario.</p>
</div>
<div class="paragraph">
<p>Now let&#8217;s write our contract! You can define the contracts with Groovy DSL. Let&#8217;s create
our first HTTP contract. To do so:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Under <code>src/test/resources/contracts/beer/rest/</code>, create a
<code>shouldNotSellAnyAlcohol.groovy</code> file.</p>
</li>
<li>
<p>Call the <code>Contract.make</code> method to start defining the contract, as follows:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {

}</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>You can call the <code>description()</code> method to provide some meaningful description.</p>
</li>
</ul>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
You can use the Groovy multiline String <code>""" """</code> to have all special characters
escaped. Every new line in the String is converted into a new line character. The
following code shows an example:
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now call the <code>request { }</code> and <code>response { }</code> methods, as shown below:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s assume that we want to send a <code>POST</code> method. Call <code>method POST()</code> or <code>method "POST"</code>.</p>
</div>
<div class="admonitionblock tip">
<table>
<tr>
<td class="icon">
<div class="title">Tip</div>
</td>
<td class="content">
In Groovy, you don&#8217;t need to provide parentheses (in most cases). You can write
either <code>method POST()</code> or <code>method(POST())</code>. In both cases, the effet is the same.
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we need to provide a URL. You can set it to <code>/buy</code> by writing <code>url "/buy"</code>, as shown
in the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/buy"
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now it&#8217;s time to define the body. We want to define <code>age</code> and <code>name</code> fields. Let&#8217;s make
<code>name</code> accept any alpha unicode value. Let&#8217;s make <code>age</code> be a concrete value at this time.
We will make it dynamic in the next step. The following code sets our initial values for
both fields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>As you can see, we used the <code>$()</code> method where we&#8217;ve used the <code>anyAlphaUnicode()</code>
function to set a dynamic value.</p>
</div>
<div class="paragraph">
<p>Now we can make the <code>age</code> field be dynamic. In Spring Cloud Contract, you can either
provide the dynamic values directly in the body (as we have with the <code>name</code>) or via
<code>stubMatchers</code> and <code>testMatchers</code> sections. Let&#8217;s use the first one. We define the JSON
path for which we want to define a dynamic value, as follows:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
    }
    stubMatchers {
        jsonPath('$.age', byRegex('[2-9][0-9]'))
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Inside the <code>stubMatchers</code> section, we defined that an element matching a JSON path of
<code>$.age</code> has to match a regular expression of <code>[2-9][0-9]</code>. You can see that there are
methods other than <code>byRegex</code>. You can read about them in the
<a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_dynamic_properties_in_matchers_sections">documentation</a>.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
If you provide a value via the matchers section, then the value for the key
for which you added the matching is <strong>removed</strong> from automatic test assertion generation.
You have to provide those values manually via the matchers section.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>Now we can create the headers by calling the <code>headers { }</code> method, as shown in the
following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {

        }
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Inside that method, let&#8217;s define that we want to use the
<code>Content-Type: "application/json"</code> header. Just call <code>contentType(applicationJson())</code>
methods:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You defined how you would like the contract for the request to look!</p>
</div>
<div class="paragraph">
<p>Now we can work on the response. In the <code>response</code> block, we want to define that the
status of our response will be 200. To do so, call <code>status 200</code>, as shown in the
following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We want our response to have a body. We want to use the <code>message</code> and <code>status</code> fields.
In the <code>message</code>, we want to respond with <code>You&#8217;re drunk [name from request]. Go home!</code>
For the <code>status</code>, we want to always return a <code>NOT_OK</code> value and have a custom assertion
in our tests.</p>
</div>
<div class="paragraph">
<p>Let&#8217;s start with the <code>message</code> field. Spring Cloud Contract gives you a method, called
<code>fromRequest()</code>, that lets you specify in the response that you would like to fetch some
values from the request. In our case, the value we want in the request is inside the
request body under the <code>$.name</code> JSON path. Consequently, we can set the value of
<code>message</code> to <code>"You&#8217;re drunk [${fromRequest().body('$.name')}]. Go home!",</code>. Note that we
have a <code>""</code> Groovy String with a <code>${}</code> String interpolation in which we&#8217;re calling the
<code>fromRequest()</code> method. The following code shows how all of that works:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            message: "You're drunk [${fromRequest().body('$.name')}]. Go home!"
        )
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we have the message response that references the request. It&#8217;s time for the second
field. Until now, we always provided a single value for the dynamic parts of the
contract. Whenever we have dynamic values on one side (consumer or producer), then we
must have a concrete value on the other side. In this case, we can provide that value
manually. For the response in the stub, we need to provide a concrete value equal to
<code>NOT_OK</code>. For the generated test, we want to have a custom assertion done via the
<code>assertStatus()</code> method defined in the base class. To achieve that, we need to write
<code>$(c("NOT_OK"), p(execute('assertStatus($it)')))</code>. Let&#8217;s now analyze this syntax:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><code>c()</code> is a shortcut for <code>consumer()</code>, and <code>p()</code> is short for <code>producer(). By calling
`$(c(),p())</code>, we provide a concrete value for the consumer and a dynamic one for the
producer.</p>
</li>
<li>
<p>The <code>$(c("NOT_OK"),&#8230;&#8203;)</code> means that, for the response in the stub, for the <code>status</code>
field, we want the stub to contain a value of <code>NOT_OK</code>.</p>
</li>
<li>
<p>The <code>$(&#8230;&#8203;,p(execute('assertStatus($it)')))</code> means that we want, on the producer side,
in the autogenerated tests, to run a method defined in the base class. That method is
called <code>assertStatus()</code>. As a parameter of that method, we want to pass the value of
an element present in the response JSON. In our case, we provide a dynamic value for
the <code>$.status</code> field. <code>assertStatus($it)</code> gets translated to <code>assertStatus(read the
$.status from the response JSON)</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now we can write the response body, as shown in the following code:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            message: "You're drunk [${fromRequest().body('$.name')}]. Go home!",
            status: $(c("NOT_OK"), p(execute('assertStatus($it)')))
        )
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we may want to perform some more complex analysis of the <code>message</code> field through a
method called <code>assertMessage()</code>. There&#8217;s another way to do that: We can call the
<code>testMatchers</code> section.</p>
</div>
<div class="paragraph">
<p>Under <code>testMatchers</code>, we can define, through a JSON path, the element we want to
dynamically assert. To do so, we can add the following section:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            message: "You're drunk [${fromRequest().body('$.name')}]. Go home!",
            status: $(c("NOT_OK"), p(execute('assertStatus($it)')))
        )
        testMatchers {
            jsonPath('$.message', byCommand('assertMessage($it)'))
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The last thing to add are the response headers. We do exactly the same thing as we
previously did for the request, except that we use
<code>headers { contentType(applicationJson()) }</code>, as shown in the following example:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            message: "You're drunk [${fromRequest().body('$.name')}]. Go home!",
            status: $(c("NOT_OK"), p(execute('assertStatus($it)')))
        )
        testMatchers {
            jsonPath('$.message', byCommand('assertMessage($it)'))
        }
        headers {
            contentType(applicationJson())
        }
    }
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;re almost done. We wrote a very generic example that catches a person with any name.
However, in the requirements, we saw that a <code>starbuxman</code> person always has to get the
beer. Consequently, we need a specific case of our generic pattern. That is why we will
set the <code>priority</code> to <code>100</code> (the higher the number, the lower the priority).</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: $(anyAlphaUnicode()),
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
            message: "You're drunk [${fromRequest().body('$.name')}]. Go home!",
            status: $(c("NOT_OK"), p(execute('assertStatus($it)')))
        )
        testMatchers {
            jsonPath('$.message', byCommand('assertMessage($it)'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    priority 100
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You have created your first contract! Now we can define a version for
someone named Josh.</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Copy the file and call it <code>shouldSellAlcoholOnlyToStarbuxman.groovy</code>.</p>
</li>
<li>
<p>Set the name to <code>starbuxman</code>.</p>
</li>
<li>
<p>Set the priority to <code>10</code>.</p>
</li>
<li>
<p>Set the <code>message</code> to <code>There you go Josh!</code>.</p>
</li>
<li>
<p>Set the <code>status</code> to <code>OK</code>.</p>
</li>
</ol>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
We do not want to do any custom server-side assertions.
</td>
</tr>
</table>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">org.springframework.cloud.contract.spec.Contract.make {
    description("""
        Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
    """)
    request {
        method POST()
        url "/check"
        body(
            name: "starbuxman",
            age: 25
            )
        }
        stubMatchers {
            jsonPath('$.age', byRegex('[2-9][0-9]'))
        }
        headers {
            contentType(applicationJson())
        }
    }
    response {
        status 200
        body(
                message: "There you go Josh!",
                status: "OK"
        )
        headers {
            contentType(applicationJson())
        }
    }
    priority 10
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Congratulations! You have created all the contracts. Now we can go ahead and install the
stubs, as shown in the following code for both Maven and Gradle:</p>
</div>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">./mvnw clean install -DskipTests</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now we can go back to our consumer tests and open the <code>GrumpyBartenderControllerTest</code>
class. We want to add Stub Runner as usual. However, this time, we do not pass the port.
We want the port to be set automatically.</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@AutoConfigureStubRunner(stubsMode = StubRunnerProperties.StubsMode.LOCAL, ids = "com.example:beer-api-producer-advanced")</code></pre>
</div>
</div>
<div class="paragraph">
<p>How can you retrieve the port value then? There are two ways of doing so:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Autowire the field annotated with
<code>@Value("${stubrunner.runningstubs.artifactid.port}")</code>.</p>
</li>
<li>
<p>Use the autowired <code>StubFinder</code> interface, which includes the <code>findStub</code> method.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The following code shows an example of autowiring the field for
<code>beer-api-producer-advanced</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Value("${stubrunner.runningstubs.beer-api-producer-advanced.port}") int stubPort;

@Before
public void setupPort() {
    controller.port = stubPort;
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>The following code shows an example of using the <code>StubFinder</code> interface for
<code>beer-api-producer-advanced</code>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@Autowired StubFinder stubFinder;

@Before
public void setupPort() {
    controller.port = stubFinder.findStubUrl("beer-api-producer-advanced").getPort();
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>Let&#8217;s go with the first option (autowiring the field). We want to inject the value of the
port of the running stub into the controller. Now, when we run the tests, then they
should pass successfully.</p>
</div>
<div class="paragraph">
<p>Congratulations! As consumers, we successfully used the API of the producer for both
HTTP and messaging. Now we can file a pull request (PR) to the producer&#8217;s code with the
proposal of the contract. Let&#8217;s switch to the producer side.</p>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producer_flow_1">Producer Flow 1</h3>
<div class="imageblock">
<div class="content">
<img src="../images/producer_flow_1.png" alt="producer flow 1">
</div>
<div class="title">Figure 5. Producer takes over the PR, writes missing impl and merges the PR</div>
</div>
<div class="sect3">
<h4 id="_ide_setup">IDE setup</h4>
<div class="ulist">
<ul>
<li>
<p>Open in your IDE the <code>producer</code> project (either via Maven or Gradle)</p>
</li>
<li>
<p>We&#8217;re assuming that we&#8217;ve taken over the PR. Example of how to achieve that in "real life" for a PR
that got submitted to via a branch called <code>the_pr</code> looks like this:</p>
</li>
</ul>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">git fetch origin
git checkout -b the_pr origin/the_pr
git merge master</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>The idea of Spring Cloud Contract is about stub and contract validity. Right now we have a set of
contracts defined but we haven&#8217;t tested it against the producer side. Time to change that!</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_setting_up_the_spring_cloud_contract_plugin">Setting up the Spring Cloud Contract plugin</h4>
<div class="ulist">
<ul>
<li>
<p>Spring Cloud Contract can generate tests from your contracts to ensure that your implementation&#8217;s API
is compatible with the defined contract. Let&#8217;s set up the project to start generating tests.</p>
<div class="ulist">
<ul>
<li>
<p>Spring Cloud Contract needs a base class that all of the generated tests will extend. Currently
we support 3 different ways of defining a base class (you can read more about this in the
Spring Cloud Contract documentation for <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin">Gradle</a>
and <a href="https://cloud.spring.io/spring-cloud-contract/spring-cloud-contract.html#_configure_plugin_2">Maven</a>)</p>
<div class="ulist">
<ul>
<li>
<p>a single class for all tests</p>
</li>
<li>
<p>convention based naming (takes 2 last package names and appends <code>Base</code>. Having a contract
<code>src/test/resources/contracts/foo/bar/shouldDoSth.groovy</code> would create a test class called
<code>BarTest</code> that would extend <code>FooBarBase</code> class.</p>
</li>
<li>
<p>manual mapping (you can state that contracts matching certain regular expression will have to
have a base class with fully qualified name equal to X)</p>
</li>
</ul>
</div>
</li>
<li>
<p>In the following example we&#8217;ll play with convention based naming</p>
<div class="ulist">
<ul>
<li>
<p>For Maven under the plugin setup you have to set up the plugin configuration
<code>&lt;configuration&gt;&lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;&lt;/configuration&gt;</code></p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;plugin&gt;
    &lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
    &lt;artifactId&gt;spring-cloud-contract-maven-plugin&lt;/artifactId&gt;
    &lt;version&gt;${spring-cloud-contract.version}&lt;/version&gt;
    &lt;extensions&gt;true&lt;/extensions&gt;
    &lt;configuration&gt;
        &lt;packageWithBaseClasses&gt;com.example&lt;/packageWithBaseClasses&gt;
    &lt;/configuration&gt;
&lt;/plugin&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">contracts {
    packageWithBaseClasses = 'com.example'
}</code></pre>
</div>
</div>
</li>
<li>
<p>In both cases passing of that value tells the plugin that a given base class is available under
the <code>com.example</code> package</p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_generating_tests_from_contracts">Generating tests from contracts</h4>
<div class="ulist">
<ul>
<li>
<p>Let&#8217;s generate the tests! Just call:</p>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./mvnw clean install</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">$ ./gradlew clean build publishToMavenLocal</code></pre>
</div>
</div>
<div class="ulist">
<ul>
<li>
<p>Suddenly some tests should start failing. Those tests are the autogenerated tests created
by Spring Cloud Contract</p>
</li>
<li>
<p>The tests lay under <code>/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests/beer</code>
in <code>target</code> for Maven or <code>build</code> for Gradle</p>
</li>
<li>
<p>There will be a test for each folder in which you store your contracts. The name of the test class
will be the name of that folder</p>
</li>
<li>
<p>Each of the contracts will be a single test inside that test class</p>
</li>
<li>
<p>If you check out the generated tests you&#8217;ll notice that the dynamic parts of the <code>request</code> part
of the contract got converted to a concrete value. Any dynamic bits on the <code>response</code> side would be
converted into matchers.</p>
</li>
</ul>
</div>
</li>
<li>
<p>Time to fix the broken tests. We need to do that by providing the missing implementation.</p>
</li>
</ul>
</div>
</div>
<div class="sect3">
<h4 id="_fixing_broken_http_tests">Fixing broken HTTP tests</h4>
<div class="paragraph">
<p>The situation is that the generated tests have failed. We need to fix it by providing
the missing assert methods in the base class. We also need to
set up RestAssured. Let&#8217;s start with the first one:</p>
</div>
<div class="olist arabic">
<ol class="arabic">
<li>
<p>Go to <code>BeerRestBase</code>.</p>
</li>
<li>
<p>Add the missing <code>assertStatus(String status)</code> and <code>assertMessage(String message)</code>
methods (<a href="#_missing_assert_methods">or copy from the solution</a>).</p>
<div class="ulist">
<ul>
<li>
<p><code>assertStatus</code> should assert that the <code>status</code> is equal to <code>NOT_OK</code>.</p>
</li>
<li>
<p><code>assertMessage</code> should assert that the <code>message</code> contains <code>Go home!</code></p>
</li>
</ul>
</div>
</li>
<li>
<p>Add the missing Rest Assured setup by adding the <code>BuyController</code> into the list of
standalone set up classes, as shown in the following code snippet:</p>
</li>
</ol>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">RestAssuredMockMvc.standaloneSetup(..., new BuyController(), ...);</code></pre>
</div>
</div>
<div class="paragraph">
<p>This time, we are not mocking in the base class, because we already did so in the
previous tutorials. Instead, we try to make our tests pass as fast as possible.</p>
</div>
<div class="admonitionblock important">
<table>
<tr>
<td class="icon">
<div class="title">Important</div>
</td>
<td class="content">
We want our Controller to use the async servlet functionality. That&#8217;s
why we need it to return a <code>Callable&lt;Response&gt;</code>
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>To ensure that we return a <code>Callable&lt;Response&gt;</code>, we need to write our implementation of
the controller (<a href="#_buycontroller">or copy from the solution</a>) such that it has the
following characteristics:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>A POST method to the <code>/buy</code> endpoint that produces and consumes JSON</p>
</li>
<li>
<p>If the <code>Person</code> name is equal to <code>starbuxman</code>, return a <code>status</code> code of <code>OK</code> and a
<code>message</code> of <code>There you go Josh</code>.</p>
</li>
<li>
<p>If the <code>Person</code> name is not equal to <code>starbuxman</code>, return a <code>status</code> code of <code>NOT_OK</code>
and a <code>message</code> of <code>You&#8217;re drunk [name]. Go home!</code></p>
</li>
</ul>
</div>
<div class="paragraph">
<p>Now, when you run the build again, your autogenerated tests still fail. The reason for
the failure is that we used the async servlet feature but Rest Assured does not know
that. To fix that, we need to add the <code>async()</code> method in the response side of our
contracts. (<a href="#_grumpy_contracts">Check the solution</a>). Now, when you run the build again,
your tests should pass.</p>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_solutions">Solutions</h2>
<div class="sectionbody">
<div class="sect2">
<h3 id="_written_consumer_tests">Written consumer tests</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test
	public void should_give_me_a_beer_when_im_old_enough() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 22)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("THERE YOU GO"));
		//remove::end[]
	}

	@Test
	public void should_reject_a_beer_when_im_too_young() throws Exception {
		//remove::start[]
		this.mockMvc.perform(MockMvcRequestBuilders.post("/beer")
				.contentType(MediaType.APPLICATION_JSON)
				.content(this.json.write(new Person("marcin", 17)).getJson()))
				.andExpect(status().isOk())
				.andExpect(content().string("GET LOST"));
		//remove::end[]
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_adding_spring_cloud_contract_dependency">Adding Spring Cloud Contract Dependency</h3>
<div class="listingblock primary">
<div class="title">Maven</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
	&lt;groupId&gt;org.springframework.cloud&lt;/groupId&gt;
	&lt;artifactId&gt;spring-cloud-starter-contract-verifier&lt;/artifactId&gt;
	&lt;scope&gt;test&lt;/scope&gt;
&lt;/dependency&gt;</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Gradle</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">testCompile("org.springframework.cloud:spring-cloud-starter-contract-verifier")</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_proposal_of_simple_contracts_by_consumer">Proposal of simple contracts by consumer</h3>
<div class="paragraph">
<p><strong>HTTP communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Old Enough</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldGrantABeerIfOldEnough.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 22,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Too Young</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldRejectABeerIfTooYoung.groovy
org.springframework.cloud.contract.spec.Contract.make {
		description("""
Represents a successful scenario of getting a beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll grant him the beer
```

""")
	request {
		method 'POST'
		url '/check'
		body(
				age: 17,
				name: "marcin"
		)
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body("""
			{
				"status": "NOT_OK"
			}
			""")
		headers {
			contentType(applicationJson())
		}
	}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p><strong>Messaging communication</strong></p>
</div>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_consumer_controller_code">Missing consumer controller code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		ResponseEntity&lt;Response&gt; response = this.restTemplate.exchange(
				RequestEntity
						.post(URI.create("http://localhost:" + this.port + "/check"))
						.contentType(MediaType.APPLICATION_JSON)
						.body(person),
				Response.class);
		switch (response.getBody().status) {
		case OK:
			return "THERE YOU GO";
		default:
			return "GET LOST";
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_stub_logs">Stub Logs</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-bash" data-lang="bash">2017-05-11 12:16:51.146  INFO 4693 --- [           main] o.s.c.c.s.StubDownloaderBuilderProvider  : Will download stubs using Aether
2017-05-11 12:16:51.148  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Remote repos not passed but the switch to work offline was set. Stubs will be used from your local Maven repository.
2017-05-11 12:16:51.291  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is [+] - will try to resolve the latest version
2017-05-11 12:16:51.308  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is [0.0.1-SNAPSHOT]
2017-05-11 12:16:51.309  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] using remote repositories []
2017-05-11 12:16:51.317  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact [com.example:{producer_artifact}:jar:stubs:0.0.1-SNAPSHOT] to /home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar
2017-05-11 12:16:51.322  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/home/marcin/.m2/repository/com/example/{producer_artifact}/0.0.1-SNAPSHOT/{producer_artifact}-0.0.1-SNAPSHOT-stubs.jar]
2017-05-11 12:16:51.327  INFO 4693 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/tmp/contracts9053257535983128167]
2017-05-11 12:16:52.608  INFO 4693 --- [           main] ationConfigEmbeddedWebApplicationContext : Refreshing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@699e0bf0: startup date [Thu May 11 12:16:52 CEST 2017]; root of context hierarchy
2017-05-11 12:16:52.684  INFO 4693 --- [           main] f.a.AutowiredAnnotationBeanPostProcessor : JSR-330 'javax.inject.Inject' annotation found and supported for autowiring
2017-05-11 12:16:52.837  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat initialized with port(s): 8090 (http)
2017-05-11 12:16:52.851  INFO 4693 --- [           main] o.apache.catalina.core.StandardService   : Starting service Tomcat
2017-05-11 12:16:52.853  INFO 4693 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/8.5.14
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2017-05-11 12:16:52.975  INFO 4693 --- [ost-startStop-1] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 367 ms
2017-05-11 12:16:52.996  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'stub' to [/]
2017-05-11 12:16:53.000  INFO 4693 --- [ost-startStop-1] o.s.b.w.servlet.ServletRegistrationBean  : Mapping servlet: 'admin' to [/__admin/*]
2017-05-11 12:16:53.135  INFO 4693 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8090 (http)
2017-05-11 12:16:53.139  INFO 4693 --- [           main] o.s.c.contract.stubrunner.StubServer     : Started stub server for project [com.example:{producer_artifact}:0.0.1-SNAPSHOT:stubs] on port 8090</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beer_request">Beer Request</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">class BeerRequest {
	public int age;

	public BeerRequest(int age) {
		this.age = age;
	}

	public BeerRequest() {
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_listener_code">Missing listener code</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		if (verification.eligible) {
			this.eligibleCounter.incrementAndGet();
		} else {
			this.notEligibleCounter.incrementAndGet();
		}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_triggers">Missing triggers</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@Test public void should_increase_the_eligible_counter_when_verification_was_accepted() throws Exception {
		int initialCounter = this.listener.eligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("accepted_verification");
		//remove::end[]

		then(this.listener.eligibleCounter.get()).isGreaterThan(initialCounter);
	}

	@Test public void should_increase_the_noteligible_counter_when_verification_was_rejected() throws Exception {
		int initialCounter = this.listener.notEligibleCounter.get();

		//remove::start[]
		this.stubTrigger.trigger("rejected_verification");
		//remove::end[]

		then(this.listener.notEligibleCounter.get()).isGreaterThan(initialCounter);
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_dsls">Messaging DSLs</h3>
<div class="listingblock primary">
<div class="title">Positive Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendAcceptedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a positive verification message when person is eligible to get the beer

```
given:
	client is old enough
when:
	he applies for a beer
then:
	we'll send a message with a positive verification
```

""")
	// Label by means of which the output message can be triggered
	label 'accepted_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsOldEnough()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: true
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Negative Verification</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// messaging/shouldSendRejectedVerification.groovy
org.springframework.cloud.contract.spec.Contract.make {
	description("""
Sends a negative verification message when person is not eligible to get the beer

```
given:
	client is too young
when:
	he applies for a beer
then:
	we'll send a message with a negative verification
```

""")
	// Label by means of which the output message can be triggered
	label 'rejected_verification'
	// input to the contract
	input {
		// the contract will be triggered by a method
		triggeredBy('clientIsTooYoung()')
	}
	// output message of the contract
	outputMessage {
		// destination to which the output message will be sent
		sentTo 'verifications'
		// the body of the output message
		body(
            eligible: false
		)
		headers {
			header("contentType", applicationJsonUtf8())
		}
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_producercontroller_implementation">ProducerController implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">if (personCheckingService.shouldGetBeer(personToCheck)) {
    return new Response(BeerCheckStatus.OK);
}
return new Response(BeerCheckStatus.NOT_OK);</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beerrestbase">BeerRestBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(MockitoJUnitRunner.class)
public abstract class BeerRestBase {
	@Mock PersonCheckingService personCheckingService;
	@InjectMocks ProducerController producerController;

	@Before
	public void setup() {
		given(personCheckingService.shouldGetBeer(argThat(oldEnough()))).willReturn(true);
		RestAssuredMockMvc.standaloneSetup(producerController);
	}

	private TypeSafeMatcher&lt;PersonToCheck&gt; oldEnough() {
		return new TypeSafeMatcher&lt;PersonToCheck&gt;() {
			@Override protected boolean matchesSafely(PersonToCheck personToCheck) {
				return personToCheck.age &gt;= 20;
			}

			@Override public void describeTo(Description description) {

			}
		};
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_beermessagingbase">BeerMessagingBase</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">@RunWith(SpringRunner.class)
@SpringBootTest(classes = ProducerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.NONE)
@AutoConfigureMessageVerifier
public abstract class BeerMessagingBase {
	@Inject MessageVerifier messaging;
	@Autowired PersonCheckingService personCheckingService;

	@Before
	public void setup() {
		// let's clear any remaining messages
		// output == destination or channel name
		this.messaging.receive("output", 100, TimeUnit.MILLISECONDS);
	}

	public void clientIsOldEnough() {
		personCheckingService.shouldGetBeer(new PersonToCheck(25));
	}

	public void clientIsTooYoung() {
		personCheckingService.shouldGetBeer(new PersonToCheck(5));
	}
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_messaging_implementation">Messaging implementation</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">		boolean shouldGetBeer = personToCheck.age &gt;= 20;
		this.source.output().send(MessageBuilder.withPayload(new Verification(shouldGetBeer)).build());
		return shouldGetBeer;</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_buycontroller">BuyController</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	@PostMapping(value = "/buy",
			consumes = MediaType.APPLICATION_JSON_VALUE,
			produces = MediaType.APPLICATION_JSON_VALUE)
	Callable&lt;Response&gt; buy(@RequestBody Person person) {
		if ("starbuxman".equalsIgnoreCase(person.name)) {
			return () -&gt; new Response(Status.OK, "There you go Josh!");
		}
		return () -&gt;new Response(Status.NOT_OK, "You're drunk [" + person.name + "]. Go home!");
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_missing_assert_methods">Missing assert methods</h3>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code class="language-java" data-lang="java">	protected void assertStatus(String status) {
		BDDAssertions.then(status).isEqualToIgnoringCase(Status.NOT_OK.name());
	}

	protected void assertMessage(String message) {
		BDDAssertions.then(message).contains("Go home!");
	}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_grumpy_contracts">Grumpy contracts</h3>
<div class="listingblock primary">
<div class="title">Everbody</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldNotSellAnyAlcohol.groovy
package contracts.beer.rest

import org.springframework.cloud.contract.spec.Contract

Contract.make {
	description("""
Represents a grumpy waiter that is too bored to sell any alcohol for anyone.
""")
	request {
		method POST()
		url '/buy'
		body(
				name: $(anyAlphaUnicode()),
				age: 25
		)
		bodyMatchers {
			jsonPath('$.age', byRegex('[2-9][0-9]'))
		}
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body(
				message: "You're drunk [${fromRequest().body('$.name')}]. Go home!",
				status: $(c("NOT_OK"), p(execute('assertStatus($it)')))
		)
		bodyMatchers {
			jsonPath('$.message', byCommand('assertMessage($it)'))
		}
		headers {
			contentType(applicationJson())
		}
		async()
	}
	priority 100
}</code></pre>
</div>
</div>
<div class="listingblock secondary">
<div class="title">Starbuxman</div>
<div class="content">
<pre class="prettyprint highlight"><code class="language-groovy" data-lang="groovy">// rest/shouldSellAlcoholToStarbuxman.groovy
package contracts.beer.rest

import org.springframework.cloud.contract.spec.Contract

Contract.make {
	description("""
Represents a grumpy waiter that will sell alcohol only to Starbuxman.
""")
	request {
		method POST()
		url '/buy'
		body(
				name: "starbuxman",
				age: 25
		)
		bodyMatchers {
			jsonPath('$.age', byRegex('[2-9][0-9]'))
		}
		headers {
			contentType(applicationJson())
		}
	}
	response {
		status 200
		body(
				message: "There you go Josh!",
				status: "OK"
		)
		headers {
			contentType(applicationJson())
		}
		async()
	}
	priority 10
}</code></pre>
</div>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_back_to_the_main_page">Back to the Main Page</h2>
<div class="sectionbody">
<div class="paragraph">
<p><a href="../workshops.html">Click here to go back to the main page</a></p>
</div>
</div>
</div>
</div>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js"></script>
<script>prettyPrint()</script>
</body>
</html>